#ifndef __SIGEL_ENTITES_H__
#define __SIGEL_ENTITES_H__

int Entts::GetInsCount(void)
{
	return InFrustumCnt;
}

int Entts::GetOutCount(void)
{
	return OutFrustumCnt;
}

const int EC_NODEF=0x00;
const int EC_SURFACE=0x01;
const int EC_LIGHT=0x02;
const int EC_PIVOT=0x03;
const int EC_TERRAIN=0x04;
const int EC_SPRITESYSTEM=0x05;
const int EC_MD2=0x06;
const int EC_MD3=0x07;
const int EC_MD5=0x08;
const int EC_PEMMITER=0x09;
const int EC_BILLBOARD=0x0A;
const int EC_SKIN=0x0B;
const int EC_SKYBOX=0x0c;

const char FM_NONE=0x00;
const char FM_SPHERE=0x01;

const int EFX_NONE=0;
const int EFX_FULLBRIGHT=1;
const int EFX_GLOW=2;
const int EFX_FLATSHADED=4;
const int EFX_DISABLEFOG=8;
const int EFX_FULLSLIDES=16;

class Entity;

typedef std::list<Entity*> Telist; 
Telist elist;
Telist aelist;
Telist animentiteslist;

int cnt_aents;

namespace ekernel
{
	const int ENTITY=0;
	const int ANIM=1;
	const int ALPHA=2;
	const int INVISIBLE=3;

	Entity **elist[4];

	int cnt[4];
	int max[4];

	const int cash_size = 256000;

	void init();
	void AddEntity(int LIST,Entity* ent);
	void RemoveEntity(int LIST,Entity* ent);
	void deinit();
}

class Entity
{
	Entity* handle;
	bool visible;
	float x,y,z;
	float ax,ay,az;
	float sx,sy,sz;
	char* name;
	int eclass;
	void* src;
	Texture **tex;
	int ttex;
	float frmRadius;
	char frustum_mode;
	char blendmode;
	Telist* childs;
	float relevanse;
	Entity* parent;
	float shininess;
	float sinax,cosax,sinay,cosay,sinaz,cosaz;
	bool need_recalc_angles;
	bool InFrustum(void);
	Shader* shader;
	float atest;
	void(*preprocess)(Entity*);
	void(*postprocess)(Entity*);
	void(*bindshader)(Entity*);
	
	float currentframe;
	float maxframes;
	float framestep;
	float startframe;
	float endframe;

	unsigned int countlods;
	void **lods;
	float *ldist;
	int uselod;

	unsigned int lod_l;
	float lod_qd;

	Quaternion rot;
	Vector3D pos;
	Vector3D scale;

	Matrix4x4 local;
	Matrix4x4 global;

	float *mat;
	int usematrix;

	float colorr,colorg,colorb,colora;
	float aax,aay,aaz;

public:
	void as(const Entity *ent);

	int tag;
	float tagf;
	void *userdata;

	Entity();

	Entity(Light *l);
	Entity(Surface *s);	
	Entity(Terrain *t);
	Entity(SpriteSystem *ss);
	Entity(Md5Model *md5);
	Entity(Md2Model *md2);
	Entity(PEmmiter *pemmiter);
	Entity(Billboard *bilboard);
	Entity(SkinedMesh *skin);
	Entity(Sky *sky);

	Entity(unsigned int eclass_);
	
	~Entity();
	Entity(Entity& src);

	void exSetFrustumMode(char mode);
	void exFrustumRadius(float r);
	void exSrcRotate(float ax,float ay,float az);

	void Alpha(unsigned char a);
	void Alphaf(float a);

	void AlphaTest(float value);
	void Animate(float startframe,float endframe,float speed);
	void Animate(int keyframe);
	void Animate(const char *keyframe);
	void AnimStep(float twin);

	float AX();
	float AY();
	float AZ();
	void BindTex(Texture* tex_,unsigned int level);
	void BindShader(Shader* shader_);
	void BindShaderProc(void(*func)(Entity*));
	void Blend(char bmode);
	void CalcRelevanse();
	void ChangeSrc(SpriteSystem *src_);
	void ChangeSrc(Surface *src_);
	bool ChildsExists();
	void Color(unsigned char r,unsigned char g,unsigned char b,unsigned char a);
	void Colorf(float r, float g, float b, float a);
	void Color(unsigned char r,unsigned char g,unsigned char b);
	void Colorf(float r, float g, float b);
	bool Compare(const Entity* other) const;

	Entity* Copy();
	float Dist(Entity* ent);
	float Dist(float x,float y,float z);
	float Dist(float x,float z);
	int Draw();
	Entity* Find(char* name);
	void FlipVisible(void);
	float GetAlphaTest();
	int GetClass();
	float* GetMatrix();
	float GetMatrix(int index);

	int GetLocalMatrix(void *m16);
	int GetAbsoluteMatrix(void *m16);

	char* GetName();
	void GetDirY(float &dx, float &dz);

	void* GetSrc();
	float GetScaleX();
	float GetScaleY();
	float GetScaleZ();
	bool GetVisible(void);
	void Hide(void);
	void InitLOD(int count);
	int InView();
	bool ItsChild(Entity* ch);
	void Move(float dx,float dy,float dz);
	void Move(float forward);
	void MoveY(float forward);
	void MoveY(float dx,float dz);
    void Name(const char* name_);
	void Parent(Entity* ent);
	void PlaceOnTerrain(Terrain *terr, float bias, int method);
	void PreProcess(void(*func)(Entity*));
	void Point(float x,float z);
	void Point(float x,float y,float z);
	void Point(Entity *other);
	void Point(Entity *other,int fake);
	void Position(float x,float y,float z);
	void Position(const Entity* asent);
	void Position(const Vector3D &vec);
	void PositionX(float value);
	void PositionY(float value);
	void PositionZ(float value);

	void PostProcess(void(*func)(Entity*));

	void Rotate(float sx,float sy,float sz);
	void Rotate(const Entity *asent);
	void RotateX(float value);
	void RotateY(float value);
	void RotateZ(float value);
	void Scale(float sx,float sy,float sz);
	void Scale(float dests);
	void SetFrame(float frame);
	void SetLOD(unsigned int index,void *src_, float dist);
	void SetMatrix(float *om);
	void SetSrc(void *s);
	void SetX(float value);
	void SetY(float value);
	void SetZ(float value);
	void Shininess(float value);
	void Show(void);
	bool StateCompare(const Entity* other) const;
	void Translate(float dx,float dy,float dz);
	void TranslateX(float delta);
	void TranslateY(float delta);
	void TranslateZ(float delta);

	void Turn(float dx,float dy,float dz);
	void UseLOD(bool use_lod);
	void Visible(bool state);
	float X(void);
	float Y(void);
	float Z(void);
	void Zered();

	bool operator <(Entity& other) const;
};

Entity* LoadMesh(const char *file);

static int last_count_textures=0;

int SortEntitesListByState();

#endif